package com.example.exception;

import com.example.model.ErrorResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.sql.SQLException;

/**
 * SQL 异常处理器
 * 负责根据 SQLState 和错误消息进行分类，返回相应的错误响应
 */
@Component
public class SqlExceptionHandler {

    /**
     * 处理 SQL 异常，根据异常信息分类并返回相应的错误响应
     */
    public ResponseEntity<ErrorResponse> handleSqlException(SQLException ex) {
        // 优先检查错误消息中的关键词进行分类
        String message = ex.getMessage() != null ? ex.getMessage().toLowerCase() : "";
        
        // 配置相关错误
        if (isConfigurationError(message, ex.getSQLState())) {
            return createConfigurationErrorResponse();
        }
        
        // 连接相关错误
        if (isConnectionError(message, ex.getSQLState())) {
            return createConnectionErrorResponse();
        }
        
        // 默认按连接问题处理
        return createConnectionErrorResponse();
    }

    /**
     * 判断是否为配置相关错误
     */
    private boolean isConfigurationError(String message, String sqlState) {
        // 根据错误消息关键词判断
        if (message.contains("access denied") || 
            message.contains("authentication") || 
            message.contains("unknown database") || 
            message.contains("bad handshake")) {
            return true;
        }
        
        // 根据 SQLState 判断
        if (sqlState != null) {
            // 28xxx: 认证相关错误
            if (sqlState.startsWith("28")) {
                return true;
            }
            // 42000: 语法或访问规则错误
            if (sqlState.equals("42000")) {
                return true;
            }
        }
        
        return false;
    }

    /**
     * 判断是否为连接相关错误
     */
    private boolean isConnectionError(String message, String sqlState) {
        // 根据错误消息关键词判断
        if (message.contains("connection refused") || 
            message.contains("timeout") || 
            message.contains("network") || 
            message.contains("host") ||
            message.contains("communications link failure")) {
            return true;
        }
        
        // 根据 SQLState 判断
        if (sqlState != null) {
            // 08xxx: 连接相关错误
            if (sqlState.startsWith("08")) {
                return true;
            }
        }
        
        return false;
    }

    /**
     * 创建配置错误响应
     */
    private ResponseEntity<ErrorResponse> createConfigurationErrorResponse() {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(new ErrorResponse("DB_CONFIG_ERROR", "数据库配置信息有误，请检查连接参数"));
    }

    /**
     * 创建连接错误响应
     */
    private ResponseEntity<ErrorResponse> createConnectionErrorResponse() {
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
                .body(new ErrorResponse("DB_CONNECTION_ERROR", "服务端连接不通，请检查网络连通性"));
    }
} 